package cn.thoughtworks.school.services;

import cn.thoughtworks.school.entities.SimpleCodingQuiz;
import cn.thoughtworks.school.entities.SimpleCodingSubmission;
import cn.thoughtworks.school.entities.Stack;
import cn.thoughtworks.school.handlers.BusinessException;
import cn.thoughtworks.school.repositories.SimpleCodingQuizRepository;
import cn.thoughtworks.school.repositories.SimpleCodingQuizSubmissionRepository;
import cn.thoughtworks.school.repositories.StackRepository;
import cn.thoughtworks.school.requestParams.HomeworkSubmissionParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Date;
import java.util.Objects;

@Service
public class SimpleCodingSubmissionService {
    @Value("${simple-coding-quiz-jenkins-url.submission}")
    private String submissionHomeworkQuizJenkinsUrl;
    @Value("${simple-coding-quiz-jenkins-url.submission-zip}")
    private String submissionHomeworkQuizZipJenkinsUrl;
    @Value("${quiz-center-url}")
    private String jenkinsCallbackHost;
    @Autowired
    private SimpleCodingQuizSubmissionRepository simpleCodingQuizSubmissionRepository;
    @Autowired
    private SimpleCodingQuizRepository simpleCodingQuizRepository;
    @Autowired
    private StackRepository stackRepository;

    public SimpleCodingSubmission judgeCodingQuiz(HomeworkSubmissionParam data) throws BusinessException {
        String userAnswerRepo = data.getUserAnswerRepo();
        String branch = data.getBranch();
        Long quizId = data.getQuizId();
        Long assignmentId = data.getAssignmentId();
        Long studentId = data.getStudentId();

        SimpleCodingSubmission submission = revertStudentSubmission(assignmentId, quizId, studentId, userAnswerRepo, branch);
        submission = simpleCodingQuizSubmissionRepository.save(submission);
        SimpleCodingQuiz simpleCodingQuiz = simpleCodingQuizRepository.findById(quizId)
                .orElseThrow(() -> new BusinessException(
                        String.format("Unknown homeworkQuiz with id: %s", quizId)
                ));

        if (needRunScript(simpleCodingQuiz)) {
            submission = runScript(simpleCodingQuiz, userAnswerRepo, branch, submission);
        }
        return submission;
    }

    private SimpleCodingSubmission revertStudentSubmission(Long assignmentId, Long quizId, Long studentId, String userAnswerRepo, String branch) {
        if (isZipSuffix(userAnswerRepo)) {
            return new SimpleCodingSubmission(assignmentId, quizId, studentId, userAnswerRepo, new Date());
        }
        return new SimpleCodingSubmission(assignmentId, quizId, studentId, userAnswerRepo, branch, new Date());
    }

    private boolean isZipSuffix(String userAnswerRepo) {
        return userAnswerRepo.endsWith(".zip");
    }

    private boolean needRunScript(SimpleCodingQuiz simpleCodingQuiz) {
        return Objects.nonNull(simpleCodingQuiz.getEvaluateScript());
    }

    private SimpleCodingSubmission runScript(SimpleCodingQuiz simpleCodingQuiz, String userAnswerRepo, String branch, SimpleCodingSubmission submission) throws BusinessException {
        Long stackId = simpleCodingQuiz.getStackId();
        Stack stack = stackRepository
                .findById(stackId)
                .orElseThrow(() -> new BusinessException(
                        String.format("Unknown tag with id: %s", stackId)
                ));

        RestTemplate template = new RestTemplate();

        String callbackUrl = jenkinsCallbackHost + "/api/simpleCodingSubmissions/" + submission.getId();
        String jenkinsUrl = getJenkinsUrl(userAnswerRepo);
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(jenkinsUrl)
                .queryParam("user_answer_repo", userAnswerRepo)
                .queryParam("branch", branch)
                .queryParam("callback_url", callbackUrl)
                .queryParam("definitionRepo", simpleCodingQuiz.getDefinitionRepo())
                .queryParam("image", stack.getImage());

        template.exchange(builder.toUriString(), HttpMethod.POST, null, String.class);
        return submission;
    }

    private String getJenkinsUrl(String userAnswerRepo) {
        if (isZipSuffix(userAnswerRepo)) {
            return submissionHomeworkQuizZipJenkinsUrl;
        }
        return submissionHomeworkQuizJenkinsUrl;
    }

}
